<template>
  <!-- <Loading v-model="loading" text="">

  </Loading> -->
  <view class="image" :style="style" @click="previewImage">
    <image
      v-if="!isError"
      class="image-box"
      :src="src"
      :mode="mode"
      :lazy-load="lazyLoad"
      :show-menu-by-longpress="showMenuByLongpress"
      :draggable="draggable"
      :style="{ verticalAlign, borderRadius }"
      @load="onLoad"
      @error="onError"
    />
    <slot name="error" v-else>
      <!-- <view class="error-text"> 加载失败 </view> -->
      <image
        v-if="errorImgType === 'person'"
        class="image-box"
        src="https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/emptyIcon/empty-avatar.png"
        :mode="mode"
        :draggable="draggable"
        :style="{ verticalAlign, borderRadius }"
      />
      <image
        v-else-if="errorImgType === 'unit'"
        class="image-box"
        src="https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/emptyIcon/empty-unit.png"
        :mode="mode"
        :style="{ verticalAlign, borderRadius }"
      />
      <image
        v-else
        class="image-box"
        src="https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/emptyIcon/img-empty.png"
        :mode="mode"
        :style="{ verticalAlign, borderRadius }"
      />
    </slot>
  </view>
</template>

<script lang="ts" setup>
  import { ref, computed, watch, inject, onBeforeUnmount, type PropType, type Ref } from 'vue';
  import { propTypes } from '@/utils/propTypes';

  export type ErrorImgType = 'default' | 'person' | 'unit';

  type ImageMode =
    | 'scaleToFill'
    | 'aspectFit'
    | 'aspectFill'
    | 'widthFix'
    | 'heightFix'
    | 'top'
    | 'bottom'
    | 'center'
    | 'left'
    | 'right'
    | 'top left'
    | 'bottom left'
    | 'top right'
    | 'bottom right';

  type verticalAlignType =
    | 'baseline'
    | 'sub'
    | 'super'
    | 'text-top'
    | 'text-bottom'
    | 'middle'
    | 'top'
    | 'bottom';

  const props = defineProps({
    // 图片资源地址
    src: propTypes.string,

    // 图片错误时显示的空图片类型
    errorImgType: {
      type: String as PropType<ErrorImgType>,
      default: 'default',
    },

    // 宽度
    width: propTypes.string.def('320px'),

    // 高度
    height: propTypes.string.def('240px'),

    //图片裁剪、缩放的模式
    mode: {
      type: String as PropType<ImageMode>,
      default: 'aspectFill',
    },

    /**
     * middle 解决图片底部留白问题
     * baseline 解决小图时顶部留白
     */
    verticalAlign: {
      type: String as PropType<verticalAlignType>,
      default: 'middle',
    },

    borderRadius: propTypes.string,

    //图片懒加载。只针对page与scroll-view下的image有效
    lazyLoad: propTypes.bool.def(true),

    //	图片显示动画效果 仅App-nvue 2.3.4+ Android有效
    fadeShow: propTypes.bool.def(true),

    // 微信小程序2.7.0 长按识别菜单
    showMenuByLongpress: propTypes.bool.def(false),

    // 鼠标长按是否能拖动图片
    draggable: propTypes.bool.def(true),

    // 预览图片
    preview: propTypes.bool.def(false),

    // 加载背景色
    backgroundColor: propTypes.string.def('#cecece'),
    border: propTypes.string.def('none'),
    boxShadow: propTypes.string.def('none'),
  });

  const emit = defineEmits(['load', 'error', 'click']);

  const loading = ref(true);
  const isError = ref(false);
  const images = inject<Ref<string[]> | undefined>('images', undefined);

  const src = computed(
    () => {
      if (props.src) {
        loading.value = true;
        isError.value = false;
      } else {
        loading.value = false;
        isError.value = true;
        // onError();
      }
      return props.src;
    }, // `https://picsum.photos/${parseInt(props.width)}/${parseInt(props.height)}?uid=${buildUUID()}`,
  );

  watch(src, () => {});

  const style = computed(() => {
    const backgroundColor = loading.value
      ? props.backgroundColor
      : isError.value
      ? '#f5f5f5'
      : 'none';
    const obj: Partial<CSSStyleDeclaration> = {
      width: props.width,
      height: props.height,
      lineHeight: props.height,
      backgroundColor,
      borderRadius: props.borderRadius,
      border: props.border,
      boxShadow: props.boxShadow,
    };
    if (props.mode === 'widthFix') delete obj.height;
    if (props.mode === 'heightFix') delete obj.width;
    return obj;
  });

  function onLoad() {
    loading.value = false;
    emit('load');
  }

  function onError(err: any) {
    loading.value = false;
    isError.value = true;
    emit('error');
  }

  function previewImage() {
    emit('click');
    if (!props.preview || isError.value) return;
    uni.previewImage({
      current: src.value,
      urls: images?.value ?? [src.value],
      showmenu: props.showMenuByLongpress,
    });
  }
</script>
<style lang="scss" scoped>
  .image {
    display: block;
    transition: all 0.3s;
    font-size: 0;
    /* #ifndef H5 */
    margin: 0 auto;
    /* #endif */
  }

  .error-text {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 26rpx;
    color: #999;
  }
  .image-box {
    width: 100%;
    height: 100%;
    font-size: 0;
  }
</style>
